﻿using System;
using Microsoft.Practices.Unity;
using NUnit.Framework;
using Sessionizer.Core;
using Sessionizer.Tests.Abstraction;

namespace Sessionizer.Tests.Core
{
    
    public abstract class SessionResolutionTests : AbstractTest
    {
        [Test]
        public void ResolveThrowsIfNoBoundSession()
        {
            try
            {
                Container.Resolve<ISession>();
                Assert.Fail();
            }
            catch
            {
                Assert.Pass();
            }
            
        }


        [Test]
        public void ResolveViaDependencyThrows()
        {
            try
            {
                Container.Resolve<SessionDependant>();
                Assert.Fail();
            }
            catch
            {
                Assert.Pass();
            }
        }


        [Test]
        public void ResolveViaDependency()
        {
            using (var session = Container.Session())
            {
                using (session.Bind())
                {
                    var sd1 = Container.Resolve<SessionDependant>();
                    Assert.IsTrue(ReferenceEquals(sd1.Session, session));
                }
            }
        }


        [Test]
        public void SessionConstruction()
        {
            using (var session = Container.Session())
            {
                Assert.IsNotNull(session);
            }
        }


        [Test]
        public void SessionBinding()
        {
            using (var session = Container.Session())
            {
                using (session.Bind())
                {
                    var resolvedSession = Container.Resolve<ISession>();
                    Assert.IsTrue(ReferenceEquals(resolvedSession, session));
                }
            }
        }

        [Test]
        public void NestedSessionBinding()
        {
            using (var session1 = Container.Session())
            {
                using (var session2 = Container.Session())
                {
                    using (session1.Bind())
                    {
                        var resolved1 = Container.Resolve<ISession>();
                        Assert.IsTrue(ReferenceEquals(resolved1, session1));
                        using (session2.Bind())
                        {
                            var resolved2 = Container.Resolve<ISession>();
                            Assert.IsTrue(ReferenceEquals(resolved2, session2));
                        }
                    }
                }
            }
        }

        private sealed class SessionDependant
        {
            private readonly ISession _session;

            public SessionDependant(ISession session)
            {
                _session = session;
            }

            public ISession Session
            {
                get { return _session; }
            }
        }
    }
}